
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include <mobile3d/m3d.h>
#include <mobile3d/world.h>
#include <mobile3d/camera.h>
#include <mobile3d/model.h>
#include <mobile3d/imageBMP.h>
#include <mobile3d/math3d.h>
#include <mobile3d/trackball.h>
#include "data.h"
#include "roundcube.h"


#define WINDOW_W    500
#define WINDOW_H    500

#define MESH_NUM 7

using namespace M3D;

World *world = NULL;
Camera *camera = NULL;
Model *model = NULL;
ImageBMP *image = NULL;
TrackBall *trackball = NULL;
MMatrix4x4 matrix;

ROUND_CUBE_FACE faces [MESH_NUM] = {
	{afVertices_face_1, afVertIndices_face_1, afTexCoord_face_1},
	{afVertices_face_2, afVertIndices_face_2, afTexCoord_face_2},
	{afVertices_face_3, afVertIndices_face_3, afTexCoord_face_3},
	{afVertices_face_4, afVertIndices_face_4, afTexCoord_face_4},
	{afVertices_face_5, afVertIndices_face_5, afTexCoord_face_5},
	{afVertices_face_6, afVertIndices_face_6, afTexCoord_face_6},
};


static MPointF pixelPosToViewPos(int x, int y){

    return MPointF(2.0 * x / WINDOW_W - 1.0,
                   1.0 - 2.0 * y / WINDOW_H);

}

void display(){
 

	MMatrix4x4 m(matrix);
	m.rotate (trackball->rotation());
	model->setMatrix (m);

	world->prepareRender ();
	model->renderModel ();
	world->finishRender ();

	glFlush();
}

void init(){

	world = new World ();
	world->setSize (WINDOW_W, WINDOW_H);
	world->init ();

	camera = new Camera ();
	camera->setEye (0.0f, 0.0f, 5.0f);
	
	world->setCamera (camera);

	image = new ImageBMP ();
	Texture *texture = image->loadTexture ("mobile3d.bmp");


	model = new Model ();
	model->setMeshCount (MESH_NUM);

	for (int i = 0; i < MESH_NUM - 1; i++) {
    	model->setVertices(faces[i].vertices, VERTEX_NUM_FACE * 3 * sizeof(GLfloat), i);
   	 	model->setIndices(faces[i].indices, TRIANGLE_NUM_FACE * 3 * sizeof(GLshort), i);
		model->setUvs(faces[i].texcoord, VERTEX_NUM_FACE * 2 * sizeof (GLfloat), i);
    	model->setTriangleNums(TRIANGLE_NUM_FACE, i);
		if (texture != NULL)
			model->setTextureId (texture->textureId, i);

	}

    //init edges
    model->setVertices(afVertices_edges, VERTEX_NUM_EDGES * 3 * sizeof(GLfloat), 6);
    model->setIndices(afVertIndices_edges, TRIANGLE_NUM_EDGES * 3 * sizeof(GLshort), 6);
	model->setUvs(afTexCoord_edges, VERTEX_NUM_FACE * 2 * sizeof (GLfloat), 6);
    model->setTriangleNums(TRIANGLE_NUM_EDGES, 6);
	if (texture != NULL)
		model->setTextureId (texture->textureId, 6);

	model->setScale (0.5f, 0.5f, 0.5f);
	//matrix.rotate (45.0, 0.0, 0.0, 1.0);
	//matrix.scale (0.1,0.1);
	//matrix.translate (2.0f, 2.0f);
	//model->setMatrix (matrix);

	trackball = new TrackBall ();

}

void keyboard(unsigned char key, int x, int y){
  switch(key) {
    case 'q': case 'Q': case 27:
      exit(0);
      break;
  }
}

void processMouse(int button, int state, int x, int y) {

	if (button == GLUT_LEFT_BUTTON) {
    	if (state == GLUT_DOWN) {
			printf ("mouse left button is pressed.\n");

			//trackball->push (pixelPosToViewPos(x, y));
    	}
    	if (state == GLUT_UP) {
			printf ("mouse left button is released.\n"); 
/*
    		trackball->release (pixelPosToViewPos(x, y));
    		trackball->start ();
*/
		} 
	} 

}

void processMouseActiveMotion(int x, int y) {

	printf ("Mouse is moving. \n");

	//trackball->move (pixelPosToViewPos(x, y));

	glutPostRedisplay();

}


int main(int argc, char** argv){
	glutInit(&argc, argv);

  	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  	glutInitWindowSize(WINDOW_W, WINDOW_H);
  	glutInitWindowPosition(0,0);
  	glutCreateWindow("simple");

  	glutDisplayFunc(display);
  	glutKeyboardFunc(keyboard);
	glutMouseFunc(processMouse);
	glutMotionFunc(processMouseActiveMotion);

  	init();
  	glutMainLoop();

	FREEANDNULL (world);
	FREEANDNULL (camera);
	FREEANDNULL (model);
	FREEANDNULL (image);
	FREEANDNULL (trackball);

  	return 0;
}


